{windows-1251}
Unit Queue;
Interface
Const
        MAX_SIZE = 255;
Type
        t_size = byte;
        PQueue = ^TQueue;
        TQueue = Object
                Private
                        (* размер данных *)
                        Size:   t_size;
                        first:  pointer;
                        last:   pointer;
                Public
                        Constructor 	init(size_of_node:t_size);                                 
                        Destructor      done;                                  
                        Procedure       push(var arg);  
                        Procedure       pop;
                        Function        empty:boolean;
                        Function        front(var arg):boolean;
                        Function        back(var arg):boolean;
                        Procedure       move_front_to_back;
        end;
Implementation
Type
        buffer = array[1..MAX_SIZE] of byte;
        pbuffer = ^buffer;
        PNode = ^TNode;
        (*TNode - элемент очереди*)
        TNode = object
                Private
						(*размер данных, хранящихся в элементе (в байтах)*)
                        size_data:      t_size;
						(*указатель на данные*)
                        data:           pointer;
						(*указатель на следующий элемент очереди*)
                        next:           PNode;
                Public
                        Constructor init(var arg;const s:t_size);
                        Destructor      done;
                        Function get_next:PNode;
                        Procedure set_next(ptr:PNode);
                        Procedure get_data(var arg);
                       
        end;
(*
 * * * * * *
 *      TNode  *
 * * * * * *
*)
Constructor TNode.init;
var
        a: array[1..MAX_SIZE] of byte absolute arg;
        buf:pbuffer;
        i:byte;
begin
        writeln('constructor of node');
        size_data:=s;
        (*выделяем место в куче, чтобы пскопировать туда arg*)
        GetMem(data, size_data);
        buf:=data;
        (*копируем туда содержимое arg*)
        for i:=1 to size_data do
                buf^[i]:= a[i];
        next:=nil;
end;
Destructor TNode.done;
begin
        writeln('destructor node');
        (*освобождаем место, занятое данными класса*)
        FreeMem(data, size_data);
end;
Function TNode.get_next:PNode;
begin
        get_next:=next;
end;
Procedure TNode.set_next;
begin
        next:=ptr;
end;
Procedure TNode.get_data;
var
        a: array[1..MAX_SIZE] of byte absolute arg;
        buf:pbuffer;
        i:byte;
begin
        (*buf = указатель на данные, хранящиеся в узле*)
        buf:=data;
        for i:=1 to size_data do
                a[i]:= buf^[i];
end;
 
(*
 * * * * * *
 *      TQueue  *
 * * * * * *
*)
 
constructor TQueue.init;
 begin
        writeln('constructor of queue');
        Size:=size_of_node;
        first:= nil;
        last:=  nil;
 end;
 Destructor TQueue.done;
 begin
        while (first <> nil) do
                pop;
 end;
 
 Function TQueue.empty:boolean;
 begin
        if (first = nil) then
                empty:=true
        else
                empty:=false;
 end;
 
 Procedure TQueue.push;
 var
        p:      PNode;
        cur:PNode;
 begin
        (*непонятно какой конструктор будет вызываться*)
        p:=new(PNode, init(arg, size));
        (*если очередь пуста, добавляем в неё элемент*)
        if (first = nil) then
                begin
                        first:= p;
                        last:=  p;
                end
        else
                begin
                        cur:=   last;
                        cur^.set_next(p);
                        last:=  p;
                end;
 end;
Procedure TQueue.pop;
var
        p:PNode;
begin
        if (first <> nil) then
                begin
                        p:=first;
                        first:=p^.get_next;     (*сдвигаем first на следующий элемент*)
                        p^.done;                        (*удаляем первый*)
                        dispose(p);
                end;
        if (first = nil) then
                last:=nil;
end;
Function TQueue.front;
var
        p:PNode;
begin
        if empty then
                begin
                        front:=false;
                end
        else
                begin
                        front:=true;
                        p:=first;
                        p^.get_data(arg);
                end;
end;
Function TQueue.back;
var
        p:PNode;
begin
        if empty then
                begin
                        back:=false;
                end
        else
                begin
                        back:=true;
                        p:=last;
                        p^.get_data(arg);
                end;
end;
Procedure TQueue.move_front_to_back;
var
        p:PNode;
begin
        (*если в очереди только один или ниодного элемента, выходим*)
        if (first = last) then exit;
        p:=last;
        p^.set_next(first);
        p:=first;
        last:=first;
        first:=p^.get_next;
        p^.set_next(nil);
end;
end.